﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Newtonsoft.Json;
using UnityEngine;

public delegate void MsgListener(Msg msg);//事件监听的委托类型
public class NetManager
{
    private static NetManager manager;

    public static NetManager Manager
    {
        get
        {
            if (manager==null)
            {
                manager = new NetManager();
            }
            return manager;
        }
    }
    private string ip = "127.0.0.1";
    private int port = 8888;

    Socket socketClient;
    byte[] bytes = new byte[1024];

    //接收信息的队列
    Queue<string> msgQueue = new Queue<string>();

    #region 事件监听
    private Dictionary<string, MsgListener> listeners = new Dictionary<string, MsgListener>();

    public void AddListener(string msgName, MsgListener listener)
    {
        if (!listeners.ContainsKey(msgName))
        {
            listeners.Add(msgName, listener);
        }
    }

    private void Invoke(string msgName, Msg msg)
    {
        if (listeners.ContainsKey(msgName))
        {
            listeners[msgName].Invoke(msg);
        }
    }
    #endregion

    //连接异步服务器
    public void ConnectionAsync(string ip,int port)
    {
        socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        socketClient.BeginConnect(ip, port, ConnectCallBack, socketClient);
    }
    // 连接完成回调函数
    private void ConnectCallBack(IAsyncResult ar)
    {
       try
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndConnect(ar);

            Debug.Log("异步连接成功");
            //string json = "{\"Command\":\"Connected\",\"Client\":\"\",\"Value\":\"\"}";
            //msgQueue.Enqueue(json);

            //等待接收信息
            socket.BeginReceive(bytes, 0, 1024, 0, ReceiveCallback, socket);
        }
        catch (SocketException se)
        {
            Debug.LogError(se.Message);
        }
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            Socket socketClient = (Socket)ar.AsyncState;
            int count = socketClient.EndReceive(ar);
            if (count == 0)
            {
                socketClient.Close();
                Debug.Log("服务器关闭连接");
                return;

            }
            string str = Encoding.UTF8.GetString(bytes, 0, count);
            Debug.LogError("收到的异步信息是：" + str);
            msgQueue.Enqueue(str);

            //继续等待接收信息
            socketClient.BeginReceive(bytes, 0, 1024, 0, ReceiveCallback, socketClient);

        }
        catch (SocketException se)
        {
            Debug.LogError(se.Message);

        }
    }

    public void SendAsync(Msg msg)
    {
        string json = JsonConvert.SerializeObject(msg);
        SendAsync(json);
    }
    private void SendAsync(string value)
    {
        byte[] sendbytes = Encoding.UTF8.GetBytes(value);//把字符串转化为byte
        socketClient.BeginSend(sendbytes, 0, sendbytes.Length, 0, SendCallBack, socketClient);

    }

    private void SendCallBack(IAsyncResult ar)
    {
        try
        {
            Socket socketClient = (Socket)ar.AsyncState;
            int count = socketClient.EndReceive(ar);
            Debug.Log("信息发送成功，长度为：" + count);

        }
        catch (SocketException se)
        {
            Debug.LogError(se.Message);
        }
    }

    public void CloseSocket()
    {
        if (socketClient!=null)
        {
            socketClient.Close();
        }
    }
    public void Update()
    {
        if (msgQueue.Count<=0)
        {
            return;
        }
        string value = msgQueue.Dequeue();


        Msg msg = JsonConvert.DeserializeObject<Msg>(value);
        Invoke(msg.Command, msg);
    }

    public string GetInfo()
    {
        if (socketClient==null|| !socketClient.Connected)
        {
            return string.Empty;
        }
        string clientIP = ((IPEndPoint)socketClient.LocalEndPoint).Address.ToString();
        string clientPort = ((IPEndPoint)socketClient.LocalEndPoint).Port.ToString();
        return string.Format("{0}:{1}", clientIP, clientPort);
    }
}
